package org.study.collection;

import cn.hutool.core.collection.ListUtil;
import com.google.common.collect.Lists;
import lombok.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 类的描述
 *
 * @author Administrator
 * @date 2022-12-14
 */
public class ListTests {
    public static void main(String[] args) {
        testList01();
        testList02();
        testList03();
        testList04();
        testList05();
        testList06();
        testList07();
        testMap01();
        testCollections01();
        testCollection2Array01();
        testArrays01();
    }

    public static void testList01() {
        List<String> list = new ArrayList<>() {{
            this.add("test01");
            this.add("test02");
            this.add("test03");
        }};
        list.forEach(item -> System.out.println("list：" + item));

        List<String> subList = list.subList(0, 2);
        // subList() 返回的是 ArrayList 的内部类 SubList，并不是 ArrayList 而是 ArrayList 的一个视图，
        // 若强转成 ArrayList 则会抛出 ClassCastException 异常，即 java.util.RandomAccessSubList cannot be cast to java.util.ArrayList
        // ArrayList<String> cast = (ArrayList<String>) subList;
        subList.forEach(item -> System.out.println("subList：" + item));

        // 对于 SubList 子列表的所有操作最终会反映到原列表上
        subList.set(0, "test");

        System.out.println("==============================");
        subList.forEach(item -> System.out.println("subList：" + item));
        list.forEach(item -> System.out.println("list：" + item));
    }

    public static void testList02() {
        List<String> list = new ArrayList<>();
        list.add("1");
        list.add("2");
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            String item = iterator.next();
            if ("1".equals(item)) {
                iterator.remove();
            }
        }

        for (String item : list) {
            // 以上代码的执行结果肯定会出乎大家的意料，那么试一下把“1”换成“2”，会是同样的结果吗？
            if ("1".equals(item)) {
                list.remove(item);
            }
        }
    }

    public static void testList03() {
        String url = "11,";
        String[] split = url.split(",");
        Arrays.stream(split).forEach(System.out::println);

        String join = String.join(",", Lists.newArrayList("1", "2", "3", "4", "5"));
        System.out.println(join);
    }

    public static void testList04() {
        String filePath = "/user/1.png,/user/2.png,/user/3.png,/user/4.png";
        ArrayList<String> fileUrlList = Lists.newArrayList();
        ListUtil.of(filePath.split(",")).forEach(item -> fileUrlList.add("http:127.0.0.1:8080" + item));
        String joined = String.join(",", fileUrlList);
        System.out.println(joined);
    }

    public static void testList05() {
        @Data
        @NoArgsConstructor
        @AllArgsConstructor
        class User {
            private Long id;
            private String name;
        }
        List<User> list = new ArrayList<>() {{
            this.add(new User(1L, "张三"));
            this.add(new User(2L, "张三"));
            this.add(new User(1L, "张三"));
            this.add(new User(3L, "张三三"));
        }};
        List<User> collect = list.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(User::getId))), ArrayList::new));
        System.out.println(collect);
    }

    public static void testList06() {
        @Data
        @NoArgsConstructor
        @AllArgsConstructor
        class User {
            private Long id;
            private String name;
        }
        List<User> list = new ArrayList<>() {{
            this.add(new User(1L, "张三"));
            this.add(new User(2L, "李四"));
        }};
        // 在第一个位置添加一个元素
        list.add(0, new User(3L, "王五"));
        System.out.println(list);
    }

    public static void testList07() {
        List<Integer> list = Arrays.asList(1, 2, 3);
        System.out.println(list.contains(1));
    }

    public static void testMap01() {
        Map<String, String> map = new HashMap<>() {{
            this.put("key01", "value01");
            this.put("key02", "value02");
            this.put("key03", "value03");
        }};

        Set<String> keySet = map.keySet();
        Collection<String> valueCollection = map.values();
        Set<Map.Entry<String, String>> entrySet = map.entrySet();

        // 使用 Map 的 keySet()、values()、entrySet() 方法返回的集合对象时，
        // 不可以对其进行添加元素操作，否则会抛出 UnsupportedOperationException 异常
        keySet.add("set");
        valueCollection.add("collection");
    }

    public static void testCollections01() {
        // Collections 类返回的对象(如：emptyList()、singletonList()等)都是 immutableList，不可对其进行添加或者删除元素的操作
        List<String> emptyList = Collections.emptyList();
        emptyList.forEach(item -> System.out.println("emptyList：" + item));
        // emptyList.add("test");

        List<String> singletonList = Collections.singletonList("test");
        singletonList.forEach(item -> System.out.println("singletonList：" + item));
        // singletonList.add("test");
    }

    public static void testCollection2Array01() {
        List<String> list = new ArrayList<>(2);
        list.add("test01");
        list.add("test02");
        list.forEach(item -> System.out.println("list：" + item));

        // 使用集合转数组的方法时，必须使用集合中带参的 toArray(T[] array)，传入的是类型完全一致、长度为 0 的空数组
        // 直接使用无参的 toArray() 存在问题，此方法只能返回 Object[]，若强转成其它类型数组将出现 ClassCastException 错误
        // 【说明】使用带参的 toArray(T[] array) 方法，数组空间大小的 length 取值：
        // 1、等于 0：动态创建与 size 相同的数组，性能最好
        // 2、大于 0 但小于 size：重新创建大小等于 size 的数组，增加 GC 负担
        // 3、等于 size：在高并发情况下，数组创建完成之后，size 正在变大的情况下，负面影响与上相同
        // 4、大于 size：空间浪费，且在 size 处插入 null 值，存在 NPE 隐患
        String[] array = list.toArray(new String[0]);
        for (String item : array) {
            System.out.println("array：" + item);
        }
    }

    public static void testArrays01() {
        String[] array = new String[]{"test01", "test02", "test03", "test04", "test05"};
        for (String item : array) {
            System.out.println("array：" + item);
        }
        // 使用工具类 Arrays.asList() 把数组转换成集合时，不能使用其修改集合相关的方法，它的 add/remove/clear 方法会抛出 UnsupportedOperationException 异常
        // 【说明】Arrays.asList() 返回的对象是一个 Arrays 内部类，并没有实现集合的修改方法。Arrays.asList() 体现的是适配器模式，只是转换接口，后台的数据仍是数组
        List<String> list = Arrays.asList(array);
        list.forEach(item -> System.out.println("list：" + item));
        // 第一种情况：运行时异常
        // list.add("test03");
        // 第二种情况：原数组中的某个元素被修改，目标 list 也会随之而变
        array[0] = "array changed";
        // 反之亦然：目标 list 中的某个元素被修改，原数组也会随之而变
        list.set(1, "list changed");
        for (String item : array) {
            System.out.println("array：" + item);
        }
        list.forEach(item -> System.out.println("list：" + item));
    }
}
